package jobs

import (
	"bytes"
	"fmt"
	"github.com/goravel/framework/facades"
	"github.com/goravel/framework/support/json"
	"github.com/mitchellh/mapstructure"
	"github.com/spf13/viper"
	"goravel/app/models"
	"goravel/packages/spider/vars"
	"io"
	"log"
	"net/http"
	"os"
	"reflect"
	"regexp"
	"strings"
)

type CommentJob struct {
}

// Signature The name and signature of the job.
func (receiver *CommentJob) Signature() string {
	return "comment_job"
}

// Handle Execute the job.
func (receiver *CommentJob) Handle(args ...any) error {
	cursor := args[0].(int)
	aweme_id := args[1].(string)
	keywords := args[2].([]string)
	params := GetConfig("comment") // Assume getConfig() returns a slice of maps
	paramsGet := make(map[string]string)

	for key, value := range params {
		// Exclude "cookie" and "referer" keys
		if key == "cookie" || key == "referer" {
			continue
		}
		// Convert values to string based on their type
		switch v := value.(type) {
		case string:
			paramsGet[key] = v
		case int:
			//不保留小数
			paramsGet[key] = fmt.Sprintf("%d", v)
			paramsGet[key] = fmt.Sprintf("%d", v)
		case float64:
			//不保留小数
			paramsGet[key] = fmt.Sprintf("%d", int(v))
		case nil:
			paramsGet[key] = ""
		//	布尔
		case bool:
			if v {
				paramsGet[key] = "true"
			} else {
				paramsGet[key] = "false"
			}
		default:
			log.Printf("Unhandled type: %s\n", reflect.TypeOf(v).String())
		}
	}
	if aweme_id != "" {
		paramsGet["aweme_id"] = aweme_id
	}
	if cursor != 0 {
		paramsGet["cursor"] = fmt.Sprintf("%d", cursor)
	}
	realUrl := "https://www.douyin.com/aweme/v1/web/comment/list/?"
	for key, value := range paramsGet {
		realUrl += key + "=" + value + "&"
	}
	client := &http.Client{}
	request, err := http.NewRequest("GET", realUrl, nil)
	if err != nil {
		panic(err)
	}
	// 设置请求头，模拟浏览器
	headers := map[string]string{
		"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
		"Connection": "keep-alive",
		"Cookie":     params["cookie"].(string),
		"Referer":    params["referer"].(string),
	}
	// 设置请求头
	for key, value := range headers {
		request.Header.Set(key, value)
	}
	resp, err := client.Do(request)
	defer resp.Body.Close()
	if err != nil {
		fmt.Printf("请求失败，错误信息为：%v\n", err)
	}
	bodyBuffer := bytes.NewBuffer([]byte{})
	_, err = io.Copy(bodyBuffer, resp.Body)

	//转换json字符串返回
	if err != nil {
		fmt.Printf("json解析失败，错误信息为：%v\n", err)
	}

	var datainfo vars.CommentInfo
	err = json.Unmarshal(bodyBuffer.Bytes(), &datainfo)
	if err != nil {
		fmt.Printf("json解析失败，错误信息为：%v\n", err)
	}
	SaveToTable(keywords, datainfo.Comments)
	return err
}

func GetConfig(file string) map[string]interface{} {
	//获取当前项目绝对路径
	path, _ := os.Getwd()
	configPath := path + "/packages/spider/core/" + file + ".json"
	// Set the configuration file for viper
	viper.SetConfigFile(configPath)
	viper.SetConfigType("json")

	// Read the configuration file
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			fmt.Println("配置文件未找到")
		} else {
			fmt.Printf("读取配置文件时发生错误: %v\n", err)
		}
		return nil
	}

	// Convert the result to a slice of maps
	var result map[string]interface{}
	//将viper中的json转换为result
	if err := viper.Unmarshal(&result); err != nil {
		fmt.Printf("读取配置文件时发生错误: %v\n", err)
	}
	return result
}

func SaveToTable(keywords []string, comments []vars.Comment) {
	query := facades.Orm().Query()
	//正则查找：comment.Text中是否包含关键词
	pattern := strings.Join(keywords, "|")
	for _, comment := range comments {
		re := regexp.MustCompile(pattern)
		if re.MatchString(comment.Text) {
			fmt.Println("The text contains one of the words in the array.")
			comment_model := models.Comment{}
			mapstructure.Decode(comment, &comment_model)
			query.Model(&models.Comment{}).Create(&comment_model)
			if len(comment.ReplyComment) > 0 {
				for _, c := range comment.ReplyComment {
					if re.MatchString(c.Text) {
						var child models.Comment
						mapstructure.Decode(c, &child)
						query.Model(&models.Comment{}).Create(&child)
					}
				}
			}
		} else {
			fmt.Println("The text does not contain any of the words in the array.")
		}
	}
}
